package com.pro01.apirednote.service.serviceImpl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pro01.apirednote.dto.ContentRequest;
import com.pro01.apirednote.dto.ContentWithFilesResponse;
import com.pro01.apirednote.mapper.ContentMapper;
import com.pro01.apirednote.mapper.ContentFileMapper;
import com.pro01.apirednote.mapper.ContentViewMapper;
import com.pro01.apirednote.pojo.Content;
import com.pro01.apirednote.pojo.ContentFile;
import com.pro01.apirednote.pojo.PageResult;
import com.pro01.apirednote.pojo.Result;
import com.pro01.apirednote.service.ContentService;
import com.pro01.apirednote.service.ElasticsearchService;
import com.pro01.apirednote.service.CacheService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class ContentServiceImpl implements ContentService {

    private final ContentMapper contentMapper;
    private final ContentFileMapper contentFileMapper;
    private final ElasticsearchService elasticsearchService;
    private final RedisTemplate<String, Object> redisTemplate;
    private final ObjectMapper objectMapper;
    private final CacheService cacheService;
    private final ContentViewMapper contentViewMapper;
    
    // 缓存键前缀和过期时间
    private static final String CONTENT_CACHE_PREFIX = "content:detail:";
    private static final String CONTENT_FILES_CACHE_PREFIX = "content:files:";
    private static final long CONTENT_CACHE_EXPIRE_MINUTES = 30; // 30分钟

    // 发布内容
    @Override
    @Transactional
    public Result<?> createContent(Long userId, ContentRequest request) {
        Content content = new Content();
        content.setUserId(userId);
        content.setTitle(request.getTitle());
        content.setType(request.getType());
        content.setDescription(request.getDescription());
        // 确保其他字段有默认值
        content.setLikeCount(0);
        content.setCommentCount(0);
        content.setViewCount(0);
        content.setIsDeleted(false);
        // 设置日期字段
        content.setCreatedAt(java.time.LocalDateTime.now());
        content.setUpdatedAt(java.time.LocalDateTime.now());

        contentMapper.insertContent(content); // 插入内容主表（自动生成 id）
        log.info("成功创建内容，ID: {}, 标题: {}", content.getId(), content.getTitle());

        // 插入文件表
        List<String> fileUrls = request.getFileUrls();
        if (fileUrls != null && !fileUrls.isEmpty()) {
            for (String url : fileUrls) {
                ContentFile file = new ContentFile();
                file.setContentId(content.getId());
                file.setFileUrl(url);
                file.setFileType(request.getType());
                contentFileMapper.insertContentFile(file);
            }
            log.info("成功关联{}个文件到内容ID: {}", fileUrls.size(), content.getId());
        }
        
        try {
            // 添加到ElasticSearch索引
            log.info("开始将内容ID: {}添加到ElasticSearch索引", content.getId());
            elasticsearchService.indexContent(content);
            log.info("成功将内容ID: {}添加到ElasticSearch索引", content.getId());
        } catch (Exception e) {
            log.error("将内容添加到ElasticSearch索引失败，ID: {}, 错误: {}", content.getId(), e.getMessage(), e);
            // 不抛出异常，避免影响正常的内容创建流程
            // 可以考虑添加重试机制或异步重试队列
        }

        return Result.success();
    }

    // 修改内容
    @Override
    @Transactional
    public Result<?> editContent(Long userId, Long contentId, ContentRequest req) {
        Content content = contentMapper.selectById(contentId);
        if (content == null) {
            return Result.error("内容不存在");
        }
        if (!content.getUserId().equals(userId)) {
            return Result.error("无权限修改该内容");
        }

        // 更新主表字段
        content.setTitle(req.getTitle());
        content.setDescription(req.getDescription());
        contentMapper.updateContent(content);

        // 删除旧的文件记录
        contentFileMapper.deleteByContentId(contentId);

        // 插入新的 fileUrls
        List<String> fileUrls = req.getFileUrls();
        if (fileUrls != null && !fileUrls.isEmpty()) {
            for (String url : fileUrls) {
                ContentFile file = new ContentFile();
                file.setContentId(contentId);
                file.setFileUrl(url);
                file.setFileType(content.getType()); // 保持原类型不变
                contentFileMapper.insertContentFile(file);
            }
        }
        
        // 更新ElasticSearch索引
        elasticsearchService.updateIndexedContent(content);
        
        // 更新内容后，清除相关缓存
        clearContentCache(contentId);
        
        // 清除包含此内容的搜索结果缓存
        clearSearchCacheForContent(contentId);

        return Result.success();
    }

    // 删除内容
//    @Override
//    @Transactional
//    public Result<?> deleteContent(Long userId, Long contentId) {
//        Content content = contentMapper.selectById(contentId);
//        if (content == null) {
//            return Result.error("内容不存在");
//        }
//        if (!content.getUserId().equals(userId)) {
//            return Result.error("无权限删除该内容");
//        }
//
//        // 逻辑删除：设置 is_deleted = true
//        contentMapper.markContentDeleted(contentId);
//
//        // 从ElasticSearch索引中删除
//        elasticsearchService.deleteIndexedContent(contentId);
//
//        // 删除内容后，清除相关缓存
//        clearContentCache(contentId);
//
//        // 清除包含此内容的搜索结果缓存
//        clearSearchCacheForContent(contentId);
//
//        return Result.success();
//    }

    @Override
    @Transactional
    public Result<?> deleteContentWithRole(Long userId, Long contentId, String role) {
        Content content = contentMapper.selectById(contentId);
        if (content == null) {
            return Result.error("内容不存在");
        }

        boolean isOwner = content.getUserId().equals(userId);
        boolean isAdmin = "ADMIN".equalsIgnoreCase(role);

        if (!isOwner && !isAdmin) {
            return Result.error("无权限删除该内容");
        }

        // 逻辑删除
        contentMapper.markContentDeleted(contentId);

        // 删除 ElasticSearch 索引
        elasticsearchService.deleteIndexedContent(contentId);

        // 删除相关缓存
        clearContentCache(contentId);
        clearSearchCacheForContent(contentId);

        return Result.success();
    }

    // 查看我发布的内容
    @Override
    public Result<PageResult<ContentWithFilesResponse>> getMyContent(Long userId, int pageNum, int pageSize) {
        int offset = (pageNum - 1) * pageSize;
        List<Content> contentList = contentMapper.selectMyContent(userId, pageSize, offset);
        int total = contentMapper.countMyContent(userId);

        List<ContentWithFilesResponse> resultList = contentList.stream().map(content -> {
            ContentWithFilesResponse dto = new ContentWithFilesResponse();
            BeanUtils.copyProperties(content, dto);
            List<String> fileUrls = getContentFileUrls(content.getId());
            dto.setFileUrls(fileUrls);
            return dto;
        }).toList();

        PageResult<ContentWithFilesResponse> pageResult = new PageResult<>(total, resultList);
        return Result.success(pageResult);
    }

    // 查看内容详情
//    @Override
//    public Result<ContentWithFilesResponse> getContentDetail(Long contentId) {
//        // 尝试从缓存获取内容详情
//        ContentWithFilesResponse cachedContent = getContentFromCache(contentId);
//
//        if (cachedContent != null) {
//            // 缓存命中，直接返回
//            log.info("内容详情缓存命中，contentId: {}", contentId);
//            return Result.success(cachedContent);
//        }
//
//        // 缓存未命中，从数据库查询
//        log.info("内容详情缓存未命中，从数据库查询，contentId: {}", contentId);
//        Content content = contentMapper.selectById(contentId);
//        if (content == null || Boolean.TRUE.equals(content.getIsDeleted())) {
//            return Result.error("内容不存在或已被删除");
//        }
//
//        // 浏览量 +1
//        contentMapper.incrementViewCount(contentId);
//
//        ContentWithFilesResponse dto = new ContentWithFilesResponse();
//        BeanUtils.copyProperties(content, dto);
//        dto.setViewCount(content.getViewCount() + 1); // 保证返回的是最新值
//
//        // 获取文件URL列表（已包含缓存逻辑）
//        List<String> fileUrls = getContentFileUrls(contentId);
//        dto.setFileUrls(fileUrls);
//
//        // 将内容详情存入缓存
//        cacheContentDetail(contentId, dto);
//
//        return Result.success(dto);
//    }

    @Override
    public Result<ContentWithFilesResponse> getContentDetail(Long contentId, Long userId) {
        ContentWithFilesResponse cachedContent = getContentFromCache(contentId);

        if (cachedContent != null) {
            log.info("内容详情缓存命中，contentId: {}", contentId);
            return Result.success(cachedContent);
        }

        // 缓存未命中，从数据库查询
        log.info("内容详情缓存未命中，从数据库查询，contentId: {}", contentId);
        Content content = contentMapper.selectById(contentId);
        if (content == null || Boolean.TRUE.equals(content.getIsDeleted())) {
            return Result.error("内容不存在或已被删除");
        }

        // 浏览量 +1
        contentMapper.incrementViewCount(contentId);

        // 👇 如果已登录，则记录浏览行为
        if (userId != null) {
            try {
                contentViewMapper.insertOrIgnoreView(userId, contentId);
            } catch (Exception e) {
                log.error("记录浏览行为失败: userId={}, contentId={}", userId, contentId, e);
            }
        }

        ContentWithFilesResponse dto = new ContentWithFilesResponse();
        BeanUtils.copyProperties(content, dto);
        dto.setViewCount(content.getViewCount() + 1);

        List<String> fileUrls = getContentFileUrls(contentId);
        dto.setFileUrls(fileUrls);

        cacheContentDetail(contentId, dto);

        return Result.success(dto);
    }
    // 根据标题关键字搜索内容
    @Override
    public Result<PageResult<Content>> searchByTitle(String keyword, int pageNum, int pageSize) {
        int offset = (pageNum - 1) * pageSize;
        List<Content> records = contentMapper.searchByTitle(keyword, pageSize, offset);
        int total = contentMapper.countSearchResults(keyword);
        PageResult<Content> pageResult = new PageResult<>(total, records);
        return Result.success(pageResult);
    }
    
    // 获取全部内容列表（包含文件URL）
//    @Override
//    public Result<PageResult<Content>> getAllContent(int pageNum, int pageSize) {
//        int offset = (pageNum - 1) * pageSize;
//        List<Content> contentList = contentMapper.selectAllContent(pageSize, offset);
//        int total = contentMapper.countAllContent();
//
//        // 为每个内容获取对应的文件URL
//        for (Content content : contentList) {
//            List<ContentFile> files = contentFileMapper.selectByContentId(content.getId());
//            // 在这里可以处理文件URL，例如将它们添加到Content的某个字段
//            // 但由于Content类没有fileUrls字段，所以这里暂时不处理
//            // 在Controller层会转换为ContentResponse
//        }
//
//        PageResult<Content> pageResult = new PageResult<>(total, contentList);
//        return Result.success(pageResult);
//    }
    @Override
    public PageResult<ContentWithFilesResponse> listContents(int pageNum, int pageSize) {
        int offset = (pageNum - 1) * pageSize;

        List<Content> contents = contentMapper.selectContentsPaged(pageSize, offset);
        int total = contentMapper.countAllContents();

        List<ContentWithFilesResponse> result = contents.stream().map(content -> {
            ContentWithFilesResponse dto = new ContentWithFilesResponse();
            BeanUtils.copyProperties(content, dto);
            dto.setFileUrls(contentFileMapper.selectFileUrlsByContentId(content.getId()));
            return dto;
        }).toList();

        return new PageResult<>(total, result);
    }

    // 管理员删除内容
    @Override
    public Result<Void> adminDeleteContent(Long contentId, String role) {
        if (!"ADMIN".equalsIgnoreCase(role)) {
            return Result.error("无权限，管理员才能删除内容");
        }
        int rows = contentMapper.adminDeleteContentById(contentId);
        if (rows > 0) {
            // 删除内容后，清除相关缓存
            clearContentCache(contentId);
            
            // 清除包含此内容的搜索结果缓存
            clearSearchCacheForContent(contentId);
            
            return Result.success();
        } else {
            return Result.error("内容不存在或删除失败");
        }
    }

    // 获取指定内容点赞数量
    @Override
    public Result<Integer> getLikeCount(Long contentId) {
        Integer count = contentMapper.getLikeCountByContentId(contentId);
        return Result.success(count != null ? count : 0);
    }

    // 获取推荐内容（按点赞数排序）
//    @Override
//    public Result<PageResult<ContentWithFilesResponse>> getRecommendedContent(int pageNum, int pageSize) {
//        int offset = (pageNum - 1) * pageSize;
//        List<Content> contentList = contentMapper.selectRecommendedContent(pageSize, offset);
//        int total = contentMapper.countRecommendedContent();
//
//        List<ContentWithFilesResponse> resultList = contentList.stream().map(content -> {
//            ContentWithFilesResponse dto = new ContentWithFilesResponse();
//            BeanUtils.copyProperties(content, dto);
//            List<String> fileUrls = getContentFileUrls(content.getId());
//            dto.setFileUrls(fileUrls);
//            return dto;
//        }).toList();
//
//        PageResult<ContentWithFilesResponse> pageResult = new PageResult<>(total, resultList);
//        return Result.success(pageResult);
//    }
    @Override
    public PageResult<ContentWithFilesResponse> getRecommendedContents(Long userId, int pageNum, int pageSize) {
        int offset = (pageNum - 1) * pageSize;
        List<Content> contents;
        int total;

        if (userId == null) {
            // 游客推荐
            contents = contentMapper.selectTopContentsByLikes(pageSize, offset);
            total = contentMapper.countAllContents();  // 总数
        } else {
            // 登录用户推荐
            contents = contentMapper.selectUnviewedTopContents(userId, pageSize, offset);
            total = contentMapper.countUnviewedContents(userId);
        }

        List<ContentWithFilesResponse> result = contents.stream().map(content -> {
            ContentWithFilesResponse dto = new ContentWithFilesResponse();
            BeanUtils.copyProperties(content, dto);
            dto.setFileUrls(contentFileMapper.selectFileUrlsByContentId(content.getId()));
            return dto;
        }).toList();

        return new PageResult<>(total, result);
    }
    
    /**
     * 从缓存获取内容详情，如果缓存不存在则返回null
     */
    private ContentWithFilesResponse getContentFromCache(Long contentId) {
        if (contentId == null) {
            return null;
        }
        
        try {
            String cacheKey = CONTENT_CACHE_PREFIX + contentId;
            Object cachedValue = redisTemplate.opsForValue().get(cacheKey);
            
            if (cachedValue != null) {
                if (cachedValue instanceof ContentWithFilesResponse) {
                    return (ContentWithFilesResponse) cachedValue;
                } else if (cachedValue instanceof java.util.LinkedHashMap) {
                    // 处理从Redis反序列化为Map的情况
                    return objectMapper.convertValue(cachedValue, ContentWithFilesResponse.class);
                }
            }
        } catch (Exception e) {
            log.error("获取内容详情缓存失败，contentId: {}", contentId, e);
            // 异常不影响主流程
        }
        
        return null;
    }
    
    /**
     * 将内容详情存入缓存
     */
    private void cacheContentDetail(Long contentId, ContentWithFilesResponse contentDetail) {
        if (contentId == null || contentDetail == null) {
            return;
        }
        
        try {
            String cacheKey = CONTENT_CACHE_PREFIX + contentId;
            redisTemplate.opsForValue().set(cacheKey, contentDetail, CONTENT_CACHE_EXPIRE_MINUTES, TimeUnit.MINUTES);
            log.info("内容详情已缓存，contentId: {}", contentId);
        } catch (Exception e) {
            log.error("缓存内容详情失败，contentId: {}", contentId, e);
            // 缓存失败不影响主流程
        }
    }
    
    /**
     * 获取内容的文件URL列表，优先从缓存获取
     */
    private List<String> getContentFileUrls(Long contentId) {
        if (contentId == null) {
            return new ArrayList<>();
        }
        
        // 尝试从缓存获取
        String cacheKey = CONTENT_FILES_CACHE_PREFIX + contentId;
        try {
            Object cachedValue = redisTemplate.opsForValue().get(cacheKey);
            
            if (cachedValue != null) {
                log.info("文件URL列表缓存命中，contentId: {}", contentId);
                
                if (cachedValue instanceof List) {
                    return (List<String>) cachedValue;
                } else if (cachedValue instanceof Object[]) {
                    // 处理从Redis反序列化为数组的情况
                    Object[] array = (Object[]) cachedValue;
                    List<String> result = new ArrayList<>(array.length);
                    for (Object item : array) {
                        if (item != null) {
                            result.add(item.toString());
                        }
                    }
                    return result;
                }
            }
        } catch (Exception e) {
            log.error("获取文件URL列表缓存失败，contentId: {}", contentId, e);
            // 异常不影响主流程
        }
        
        // 缓存未命中，从数据库获取
        log.info("文件URL列表缓存未命中，从数据库查询，contentId: {}", contentId);
        List<String> fileUrls = contentFileMapper.selectFileUrlsByContentId(contentId);
        
        // 将结果存入缓存
        try {
            redisTemplate.opsForValue().set(cacheKey, fileUrls, CONTENT_CACHE_EXPIRE_MINUTES, TimeUnit.MINUTES);
            log.info("文件URL列表已缓存，contentId: {}", contentId);
        } catch (Exception e) {
            log.error("缓存文件URL列表失败，contentId: {}", contentId, e);
            // 缓存失败不影响主流程
        }
        
        return fileUrls;
    }
    
    /**
     * 清除内容相关的所有缓存
     */
    private void clearContentCache(Long contentId) {
        if (contentId == null) {
            return;
        }
        
        try {
            // 清除内容详情缓存
            String contentCacheKey = CONTENT_CACHE_PREFIX + contentId;
            redisTemplate.delete(contentCacheKey);
            
            // 清除文件URL列表缓存
            String filesCacheKey = CONTENT_FILES_CACHE_PREFIX + contentId;
            redisTemplate.delete(filesCacheKey);
            
            log.info("内容相关缓存已清除，contentId: {}", contentId);
        } catch (Exception e) {
            log.error("清除内容缓存失败，contentId: {}", contentId, e);
            // 清除缓存失败不影响主流程
        }
    }
    
    /**
     * 清除包含指定内容的搜索缓存
     */
    private void clearSearchCacheForContent(Long contentId) {
        if (contentId == null) {
            return;
        }
        
        try {
            // 清除包含此内容的所有搜索缓存
            long clearedCount = cacheService.clearSearchCacheContainingContent(contentId);
            log.info("已清除包含内容ID {} 的搜索缓存，共{}条", contentId, clearedCount);
        } catch (Exception e) {
            log.error("清除搜索缓存失败，contentId: {}", contentId, e);
            // 清除缓存失败不影响主流程
        }
    }
}
